﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.TextFormatting;
using System.Windows;
using System.Windows.Media;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Reflection;

namespace SDF.TextFormatting
{
    public class SmartTextEmbeddedObject: TextEmbeddedObject
    {
        #region Constructor

        public SmartTextEmbeddedObject(UIElementContainer source)
        {
            Source = source;
            _Properties = new SmartTextRunProperties(source);
        }

        #endregion

        #region Source Property

        public UIElementContainer Source { get; private set; }

        protected Size RenderSize { get; private set; }

        #endregion

        #region Overridden Properties and Methods

        public override LineBreakCondition BreakAfter
        {
            get { return LineBreakCondition.BreakPossible; }
        }

        public override LineBreakCondition BreakBefore
        {
            get { return LineBreakCondition.BreakPossible; }
        }

        public override TextRunProperties Properties
        {
            get { return _Properties; }
        }
        private TextRunProperties _Properties;


        public override Rect ComputeBoundingBox(bool rightToLeft, bool sideways)
        {
            Size desiredSize = Source.Child.DesiredSize;

            double height = !sideways ? desiredSize.Height : desiredSize.Width;
            double width = !sideways ? desiredSize.Width : desiredSize.Height;

            double baselineOffset = (double)Source.Child.GetValue(TextBlock.BaselineOffsetProperty);
            if (!sideways && !double.IsNaN(baselineOffset))
            {
                height = baselineOffset;
            }
            return new Rect(0.0, -height, width, height);
        }

        public override void Draw(DrawingContext drawingContext, Point origin, bool rightToLeft, bool sideways)
        {
            var offset = new TranslateTransform(origin.X, 0);
            drawingContext.PushTransform(offset);
            Source.Child.Draw(drawingContext);
            drawingContext.Pop();
        }

        public override TextEmbeddedObjectMetrics Format(double remainingParagraphWidth)
        {
            var containerSize = Source.GetParagraphSize();
            if (double.IsNaN(containerSize.Height))
                containerSize.Height = double.PositiveInfinity;
            if (containerSize.Height < 0)
                containerSize.Height = 0;

            if (double.IsNaN(containerSize.Width))
                containerSize.Width = remainingParagraphWidth;
            if (containerSize.Width < 0)
                containerSize.Width = 0;

            RenderSize = Arrange(Source.Child, containerSize);
            double height = RenderSize.Height;
            double baselineOffset = (double)Source.Child.GetValue(TextBlock.BaselineOffsetProperty);
            if (!Double.IsNaN(baselineOffset))
            {
                height = baselineOffset;
            }
            return new TextEmbeddedObjectMetrics(RenderSize.Width, RenderSize.Height, height);
        }

        public override bool HasFixedSize
        {
            get { return true; }
        }

        public override CharacterBufferReference CharacterBufferReference
        {
            get
            {
                return new CharacterBufferReference(string.Empty, 0);
            }
        }

        public override int Length
        {
            get { return 1; }
        }

        #endregion

        #region Arrange Method

        private static Size Arrange(UIElement element, Size availableSize)
        {
            element.Measure(availableSize);
            element.Arrange(new Rect(element.DesiredSize));
            return element.DesiredSize;
        }

        #endregion

    }
}
